package virtualTabletop;

import java.util.ArrayList;

import monster.Monster;
import player.PlayerCharacter;
import powers.Power;
import character.Character;

/**
 * Making everything happen.
 * 
 * @author bjo013
 * 
 */
public class VirtualTabletop
{

	private ArrayList<Character> roundlist = new ArrayList<Character>();

	private Character TURN;
	private int walked;
	private boolean hasAttacked;
	private int index;

	/**
	 * Constructor for the virtual tabletop.
	 */
	public VirtualTabletop()
	{
		roundlist.add(CharacterCreator.createPlayer());
		roundlist.add(CharacterCreator.createPlayer2());
		roundlist.add(CharacterCreator.createMonster());
		roundlist.add(CharacterCreator.createMonster2());

		roundlist.get(0).setTarget(roundlist.get(3));
		roundlist.get(1).setTarget(roundlist.get(2));
		roundlist.get(2).setTarget(roundlist.get(0));
		roundlist.get(3).setTarget(roundlist.get(1));

		walked = 0;
		initiative(roundlist);
		index = 0;
		TURN = roundlist.get(index);
		hasAttacked = false;

	}

	private void initiative(ArrayList<Character> roundlist)
	{
		for (int i = 0; i < roundlist.size(); ++i)
		{
			roundlist.get(i).setInitiative();
			for (int j = 0; j < i; ++j)
			{
				if (roundlist.get(j).getInitiative() < roundlist.get(i)
						.getInitiative())
				{
					Character temp = roundlist.get(j);
					roundlist.set(j, roundlist.get(i));
					roundlist.set(i, temp);
				}
			}
		}
	}

	/**
	 * gives the turn away.
	 */
	public void nextTurn()
	{
		index++;
		if (!(index < roundlist.size()))
		{
			index = 0;
		}

		TURN = roundlist.get(index);
		if (!TURN.isAlive())
		{
			nextTurn();
		}
		walked = 0;
		hasAttacked = false;
	}

	/**
	 * calculates an attack
	 * 
	 * @param defender
	 *            the defender of the attack
	 * @return a String event of the attack
	 */
	public String attack(Character defender)
	{
		String theAttack = new String();
		if (!hasAttacked && defender.isAlive())
		{
			if (TURN.getPosition().closeTo(defender.getPosition()))
			{
				Power attackPower = TURN.getPowers().get(0);

				int attack = Die.d20.roll()
						+ TURN.getStatMod(attackPower.attackWith());
				int defense = defender.getDefense(attackPower.defenseAgainst());

				theAttack = TURN.getName() + " attacks " + defender.getName()
						+ ".\n";
				theAttack += TURN.getName() + " rolls " + attack + " against "
						+ defender.getName() + "s " + defense + ".\n";

				if (attack >= defense)
				{
					int dmg = attackPower.rollDamage(TURN.getWeapon(), TURN
							.getStatMod(attackPower.attackWith()));
					int defenderHp = defender.takeDamage(dmg);
					theAttack += TURN.getName() + " does " + dmg
							+ " in damage to " + defender.getName() + ".\n"
							+ defender.getName() + " got " + defenderHp
							+ " hit points left.\n\n";
				}
				else
				{
					theAttack += TURN.getName() + " misses!\n\n";
				}

				if (defender.getHP() <= 0)
				{
					defender.setDead();
					theAttack += defender.getName() + " died!\n";

					for (Character m : roundlist)
					{
						if (m.getClass() != TURN.getClass() && m.isAlive())
						{
							TURN.setTarget(m);
						}
					}
				}

				hasAttacked = true;
			}
			else
			{
				theAttack = defender.getName() + " is too far away!\n\n";
			}
		}
		return theAttack;
	}

	/**
	 * returns the character whose turn it is.
	 * 
	 * @return character
	 */
	public Character getTURN()
	{
		return TURN;
	}

	/**
	 * returns the list of characters in order of turn.
	 * 
	 * @return arraylist of whose turn it is.
	 */
	public ArrayList<Character> getRoundlist()
	{
		return roundlist;
	}

	/**
	 * moves a character in a direction
	 * 
	 * @param d
	 *            the direction to move in
	 */
	public void move(Direction d)
	{
		if (walked < TURN.getSpeed())
		{
			TURN.getPosition().move(d);
		}
		++walked;
	}

	/**
	 * Makes the character move towards this point
	 * 
	 * @param x
	 *            the x-coord.
	 * @param y
	 *            the y-coord.
	 */
	public void walkTowards(int x, int y)
	{
		if (walked < TURN.getSpeed())
		{
			TURN.getPosition().moveTowards(new Position(x, y));
		}
		++walked;
	}

	/**
	 * checks if someone has won
	 * 
	 * @return writes who won.
	 */
	public String winCheck()
	{
		int countMonsters = 0;
		int countPlayers = 0;
		for (Character c : roundlist)
		{
			if (c.getClass() == Monster.class && c.isAlive())
			{
				countMonsters++;
			}
			if (c.getClass() == PlayerCharacter.class && c.isAlive())
			{
				countPlayers++;
			}
		}

		if (countMonsters == 0 || countPlayers == 0)
		{

			if (countMonsters == 0)
			{
				return "The players won!";
			}
			else
			{
				return "The monsters won!";
			}

		}
		else
		{
			return new String();
		}
	}
}
